
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using GruntXProductions;
using Viper;
using Viper.Opcodes;

namespace Diamond
{
	public enum VType
    {
            Dword = 1,
            Word = 2,
            String = 3,
            Pointer = 4,
            Byte = 5,
            DArray = 6,
            StringArray = 7,
            Float = 8,
            Object = 9,
            Boolean = 10,
            NotFound = 11,
    }
	public class Variable
    {
            public string Name;
            public string RealName;
            public string Class;
            public VType Type;

    }
	public class SymbolTable
	{
		public Stack<Scope> scopes = new Stack<Scope>();
		private static uint tmpIndex = 0;
		public class Scope
        {
			public string Name;
            public List<Variable> Variables = new List<Variable> ();
        }
		public string CreateTempString(string val)
		{
			CodeGen.Assembler.CreateString(tmpIndex.ToString() + "___stringLiteral",val);
			tmpIndex++;
			return (tmpIndex - 1).ToString() + "___stringLiteral";
		}
		public void DeclareInt32(string name)
		{
			Variable v = new Variable();
			v.RealName = getScopeName() + name;
			v.Name = name;
			v.Type = VType.Dword;
			scopes.Peek().Variables.Add(v);
			CodeGen.Assembler.CreateBuffer(v.RealName,4);
		}
        public void DeclareBool(string name)
        {
            Variable v = new Variable();
            v.RealName = getScopeName() + name;
            v.Name = name;
            v.Type = VType.Boolean;
            scopes.Peek().Variables.Add(v);
            CodeGen.Assembler.CreateBuffer(v.RealName, 4);
        }
		public void DeclareString(string name)
		{
			Variable v = new Variable();
			v.RealName = getScopeName() + name;
			v.Name = name;
			v.Type = VType.String;
			scopes.Peek().Variables.Add(v);
			CodeGen.Assembler.CreateBuffer(v.RealName,4);
		}
		public VType GetType(string T)
		{
			foreach(Scope sc in this.scopes)
			{
				foreach(Variable v in sc.Variables)
				{
					if(v.Name == T)
						return v.Type;
				}
			}
            return VType.NotFound;
		}
		public bool Exists(string T)
		{
			foreach(Scope sc in this.scopes)
			{
				foreach(Variable v in sc.Variables)
				{
					if(v.Name == T)
						return true;
				}
			}
			return false;
		}
		public string getScopeName()
		{
			string ret = "_";
			foreach(Scope sc in this.scopes)
			{
				ret += sc.Name + "_";
			}
			return ret + "__";
		}
		public void BeginScope(string name)
		{
			Scope sc = new Scope();
			sc.Name = name;
			scopes.Push(sc);
		}
		public void BeginScope()
		{
			Scope sc = new Scope();
			sc.Name = getScopeName() + "_scope_" + tmpIndex.ToString();
			scopes.Push(sc);
			tmpIndex++;
		}
		public void EndScope()
		{
			scopes.Pop();
		}
		public SymbolTable()
		{
		}
		public string this[string Var]
		{
			get
			{
				foreach(Scope sc in this.scopes)
				{
					foreach(Variable v in sc.Variables)
					{
						if(v.Name == Var)
							return v.RealName;
					}
				}
				return "";
			}
		}
	}
}